﻿/*
 * @author: wizardc
 */

using System;
using System.Collections.Generic;
using UnityEngine;

namespace Dou.UI
{
    /// <summary>
    /// UI 层级控制器
    /// 1. 需要手动设定根节点，根节点会设定最基础的层级，理论上其下方的子节点层级会大于自己根节点层级并小于下一个根节点的层级，即分层；
    /// 2. 非根节点支持调整当前节点的 Canvas 组件的层级，设定的层级会加上其父节点的层级，父节点会向上查找直到根节点；
    /// 3. 支持控制下方所有 Render 节点的层级（主要用来控制特效层级），支持动态查找和静态查找2种方式；
    /// </summary>
    public class UISortingOrderController : MonoBehaviour
    {
        /// <summary>
        /// 控制模式
        /// </summary>
        [Flags]
        public enum Mode
        {
            /// <summary>
            /// 什么也不控制，只作为中转
            /// </summary>
            None = 0,
            /// <summary>
            /// 控制子节点下面的 Renderer 组件
            /// </summary>
            Renderer = 1,
            /// <summary>
            /// 动态查找控制子节点下面的 Renderer 组件
            /// </summary>
            DynamicRenderer = 1 << 1,
            /// <summary>
            /// 控制 Canvas 组件
            /// </summary>
            Canvas = 1 << 2
        }

        [SerializeField]
        private bool _isRoot;

        [SerializeField]
        private int _localOrder;

        [SerializeField]
        private Mode _controlMode;

        [SerializeField]
        [HideInInspector]
        private bool _isCollected;

        [SerializeField]
        private Canvas _targetCanvas;

        [SerializeField]
        private List<Renderer> _targetRenderers;

        private readonly Dictionary<UISortingOrderController, UISortingOrderController> _children = new Dictionary<UISortingOrderController, UISortingOrderController>();
        private UISortingOrderController _parent;

        /// <summary>
        /// 是否为根节点
        /// </summary>
        public bool isRoot
        {
            set
            {
                if (_isRoot == value)
                {
                    return;
                }
                _isRoot = value;
                OnOrderChanged();
            }
            get => _isRoot;
        }

        /// <summary>
        /// 父级控制器
        /// </summary>
        public virtual UISortingOrderController parent
        {
            set
            {
                if (_parent == value)
                {
                    return;
                }
                if (_parent != null)
                {
                    _parent.Unregister(this);
                }
                _parent = value;
                ForceRefresh();
            }
            get => _parent;
        }

        /// <summary>
        /// 控制模式
        /// </summary>
        public Mode controlMode
        {
            set
            {
                if (value == _controlMode)
                {
                    return;
                }
                _controlMode = value;
                ForceRefresh();
            }
            get => _controlMode;
        }
        
        /// <summary>
        /// 自身层级
        /// </summary>
        public int localOrder
        {
            set
            {
                if (value == _localOrder)
                {
                    return;
                }
                _localOrder = value;
                OnOrderChanged();
            }
            get => _localOrder;
        }

        /// <summary>
        /// 实际层级
        /// </summary>
        public virtual int order
        {
            get
            {
                if (_isRoot || parent == null)
                {
                    return _localOrder;
                }
                return _parent.order + _localOrder;
            }
        }

        void OnEnable()
        {
            if (_parent == null)
            {
                _parent = GetParent();
            }
            if (_parent != null)
            {
                _parent.Register(this);
            }
            Refresh(order);
        }

        private UISortingOrderController GetParent()
        {
            if (_isRoot)
            {
                return null;
            }
            var parent = transform.parent;
            while (parent != null)
            {
                var component = parent.GetComponent<UISortingOrderController>();
                if (component != null)
                {
                    return component;
                }
                parent = parent.parent;
            }
            return null;
        }

        /// <summary>
        /// 注册子控制器
        /// </summary>
        private void Register(UISortingOrderController child)
        {
            _children[child] = child;
        }

        protected virtual void OnOrderChanged()
        {
            Refresh(order);
            foreach (var kv in _children)
            {
                kv.Value.OnParentOrderChanged();
            }
        }

        protected virtual void OnParentOrderChanged()
        {
            Refresh(order);
            foreach (var kv in _children)
            {
                kv.Value.OnParentOrderChanged();
            }
        }

        protected virtual void OnTransformParentChanged()
        {
            MarkParentMaybeChanged();
        }
        
        /// <summary>
        /// 标记父级控制器可能改变了
        /// </summary>
        public void MarkParentMaybeChanged()
        {
            var parent = GetParent();
            if (parent == _parent)
            {
                return;
            }
            if (_parent != null)
            {
                _parent.Unregister(this);
            }
            _parent = parent;
            if (parent != null)
            {
                parent.Register(this);
            }
            Refresh(order);
        }

        protected virtual void OnTransformChildrenChanged()
        {
            // 根节点或者没有设定动态查找模式就不处理
            if (_isRoot || (_controlMode & Mode.DynamicRenderer) <= Mode.None)
            {
                return;
            }
            _isCollected = false;
            Refresh(order);
        }
        
        /// <summary>
        /// 刷新设置
        /// </summary>
        protected virtual void Refresh(int order)
        {
            // 控制 Canvas 组件
            if ((_controlMode & Mode.Canvas) > Mode.None)
            {
                if (_targetCanvas == null)
                {
                    _targetCanvas = transform.GetComponent<Canvas>();
                }
                if (_targetCanvas != null)
                {
                    _targetCanvas.overrideSorting = true;
                    _targetCanvas.sortingOrder = order;
                }
            }
            // 控制子级 Render 没有设置就不处理
            if ((_controlMode & Mode.Renderer) <= Mode.None && (_controlMode & Mode.DynamicRenderer) <= Mode.None)
            {
                return;
            }
            // 动态收集的情况
            if (!_isCollected || !Application.isPlaying)
            {
                CollectRenders();
            }
            // 调整收集的所有 Render
            for (var i = 0; i < _targetRenderers.Count; i++)
            {
                _targetRenderers[i].sortingOrder = order;
            }
        }

        /// <summary>
        /// 收集当前节点可以控制的所有 Render
        /// 1. 会逐级向下查找；
        /// 2. 碰到挂载了 UISortingOrderController 组件的节点该节点就不向下查找了；
        /// </summary>
        private void CollectRenders()
        {
            if (_targetRenderers == null)
            {
                _targetRenderers = new List<Renderer>();
            }
            else
            {
                _targetRenderers.Clear();
            }
            for (var i = 0; i < transform.childCount; i++)
            {
                CollectRenderers(transform.GetChild(i), _targetRenderers);
            }
        }

        private void CollectRenderers(Transform transform, List<Renderer> collector)
        {
            if (transform.GetComponent<UISortingOrderController>() != null)
            {
                return;
            }
            var component = transform.GetComponent<Renderer>();
            if (component != null)
            {
                collector.Add(component);
            }
            for (int i = 0; i < transform.childCount; i++)
            {
                CollectRenderers(transform.GetChild(i), collector);
            }
        }

        /// <summary>
        /// 强制刷新
        /// </summary>
        [ContextMenu("强制刷新")]
        public void ForceRefresh()
        {
            if (_parent == null)
            {
                _parent = GetParent();
            }
            if (_parent != null)
            {
                _parent.Unregister(this);
                _parent.Register(this);
            }
            Refresh(order);
        }

        /// <summary>
        /// 缓存找到的目标
        /// </summary>
        private void CacheTargets()
        {
            _isCollected = false;
            _targetCanvas = null;
            _targetRenderers = null;
            Refresh(order);
            _isCollected = true;
        }
        
        void OnDisable()
        {
            if (_parent != null)
            {
                _parent.Unregister(this);
            }
        }
        
        /// <summary>
        /// 移除子控制器的注册
        /// </summary>
        private void Unregister(UISortingOrderController child)
        {
            _children.Remove(child);
        }
    }
}
